package cn.schoolwow.flow.monitor.module.business.testcase.flow;

import cn.schoolwow.ams.domain.block.common.operation.CustomerMessage;
import cn.schoolwow.ams.module.block.listBlock.common.domain.operation.ListBlockRequest;
import cn.schoolwow.flow.monitor.domain.FlowMonitorOption;
import cn.schoolwow.flow.monitor.entity.TestCase;
import cn.schoolwow.flow.monitor.module.business.testcase.domain.TestCaseFlowContext;
import cn.schoolwow.quickdao.domain.database.dml.UpdateType;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.dto.FlowContextDataRange;
import cn.schoolwow.quickflow.exception.QuickFlowRuntimeException;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.util.ArrayList;
import java.util.List;

public class ExecuteTestCaseFlow implements BusinessFlow {
    private Logger logger = LoggerFactory.getLogger(ExecuteTestCaseFlow.class);

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setTestCaseList(flowContext);
        setTestCaseFlowContextList(flowContext);
        executeTestCase(flowContext);
    }

    @Override
    public String name() {
        return "执行测试用例流程";
    }

    private void setTestCaseList(FlowContext flowContext){
        ListBlockRequest listBlockRequest = flowContext.checkInstanceData(ListBlockRequest.class);
        ApplicationContext applicationContext = flowContext.checkInstanceData(ApplicationContext.class);
        FlowMonitorOption flowMonitorOption = applicationContext.getBean(FlowMonitorOption.class);

        List<TestCase> testCaseList = new ArrayList<>();
        if("执行全部测试用例".equalsIgnoreCase(listBlockRequest.label)){
            testCaseList.addAll(flowMonitorOption.dao.query(TestCase.class)
                    .execute()
                    .getList());
        }else if("执行分类流程".equalsIgnoreCase(listBlockRequest.label)){
            String categoryName = listBlockRequest.search.getString("categoryName");
            Validate.notEmpty(categoryName, "请选择分类名称");
            testCaseList.addAll(flowMonitorOption.dao.query(TestCase.class)
                    .addQuery("categoryName", categoryName)
                    .execute()
                    .getList());
        }else{
            if(null!=listBlockRequest.array){
                testCaseList.addAll(listBlockRequest.array.toJavaList(TestCase.class));
            }else{
                testCaseList.add(listBlockRequest.row.toJavaObject(TestCase.class));
            }
            for(TestCase testCase:testCaseList){
                testCase.setCategoryName(testCase.getCategoryName().replace(",","-"));
            }
        }

        flowContext.putCurrentFlowData("testCaseList", testCaseList);
    }

    private void setTestCaseFlowContextList(FlowContext flowContext){
        List<TestCase> testCaseList = (List<TestCase>) flowContext.checkData("testCaseList");

        List<String> categoryNameList = QueryInstanceList.newQuery(testCaseList)
                .execute()
                .getSingleFieldValueList("categoryName");

        flowContext.startFlow(new GetTestCaseContextListFlow())
                .putCurrentCompositeFlowData("categoryNameList", categoryNameList)
                .execute();
        List<TestCaseFlowContext> testCaseFlowContextList = flowContext.getData("testCaseFlowContextList", List.class);
        if(null==testCaseFlowContextList||testCaseFlowContextList.isEmpty()){
            throw new IllegalArgumentException("当前测试用例执行列表为空");
        }
    }

    private void executeTestCase(FlowContext flowContext){
        List<TestCaseFlowContext> testCaseFlowContextList = flowContext.checkData("testCaseFlowContextList", List.class);
        List<TestCase> testCaseList = flowContext.checkData("testCaseList", List.class);

        int successCount = 0, failCount = 0;
        for(TestCase testCase:testCaseList) {
            TestCaseFlowContext testCaseFlowContext = QueryInstanceList.newQuery(testCaseFlowContextList)
                    .addQuery("categoryName", testCase.getCategoryName())
                    .addQuery("name", testCase.getName())
                    .execute()
                    .checkOne();
            flowContext.putInstanceData(testCaseFlowContext.testCaseFlow, BusinessFlow.class, FlowContextDataRange.CurrentFlow);
            flowContext.putInstanceData(testCase, FlowContextDataRange.CurrentFlow);
            executeSingleTestCase(flowContext);
            if(flowContext.containKey("hasException")){
                failCount++;
            }else{
                successCount++;
            }
            flowContext.removeData("hasException");
        }

        CustomerMessage customerMessage = null;
        if(successCount==0){
            customerMessage = new CustomerMessage("danger","测试用例执行失败");
        }else if(failCount==0){
            customerMessage = new CustomerMessage("测试用例执行成功");
        }else{
            customerMessage = new CustomerMessage("danger", "测试用例执行成功"+successCount+"个,执行失败:"+failCount+"个");
        }
        flowContext.putInstanceData(customerMessage);
    }

    private void executeSingleTestCase(FlowContext flowContext) {
        BusinessFlow testCaseFlow = flowContext.checkInstanceData(BusinessFlow.class);
        TestCase testCase = flowContext.checkInstanceData(TestCase.class);
        ApplicationContext applicationContext = flowContext.checkInstanceData(ApplicationContext.class);
        FlowMonitorOption flowMonitorOption = applicationContext.getBean(FlowMonitorOption.class);

        System.out.println("开始执行测试用例["+testCase.getName()+"]");
        try {
            FlowContext testcaseFlowContext = flowMonitorOption.testcaseQuickFlow.startFlow(testCaseFlow)
                    .putData("testcaseId", testCase.getId())
                    .putData("categoryName", testCase.getCategoryName())
                    .execute();
            testCase.setPass(true);
            testCase.setException(null);
            testCase.setBrokenReason(testcaseFlowContext.getBrokenReason());
        }catch (Exception e){
            if(e instanceof QuickFlowRuntimeException){
                QuickFlowRuntimeException ex = (QuickFlowRuntimeException) e;
                e = ex.targetException;
            }
            testCase.setPass(false);
            testCase.setException(e.getMessage());
            flowContext.putData("hasException", true);
            logger.error(e.getMessage(), e);
        }finally {
            flowMonitorOption.dao.updateType(UpdateType.UpdateByUniqueKey).update(testCase);
            System.out.println("执行完毕测试用例["+testCase.getName()+"]");
        }
    }

}
